#ifndef ACTION_EXECUTOR_H_20221006
#define ACTION_EXECUTOR_H_20221006

#include <deque>
#include <functional>

#if ENABLE_ACTION_LOCK
#include <mutex>
#endif //ENABLE_ACTION_LOCK

#include "event_id.h"

namespace action {

class Action;

using ActionId = int;

class Executor {
 public:
  virtual ~Executor();

 public:
  ActionId append(Action *action);
  ActionId current() const;

  bool skip();
  bool cancel(ActionId action_id);
  size_t size() const;

  //! set callbacks
  using ActionCallback = std::function<void(ActionId)>;
  using Callback = std::function<void()>;
  void setActionStartedCallback(const ActionCallback &cb) { action_started_cb_ = cb; }
  void setActionFinishedCallback(const ActionCallback &cb) { action_finished_cb_ = cb; }
  void setAllFinishedCallback(const Callback &cb) { all_finished_cb_ = cb; }

 public:
  void onEvent(EventId event_id, void *event_data = nullptr);

 private:
  ActionId allocActionId();
  void run();

 private:
  struct Item {
    ActionId id;
    Action *action;
  };
  std::deque<Item> action_deque_;
  ActionId action_id_alloc_counter_ = 0;

  ActionCallback  action_started_cb_;
  ActionCallback  action_finished_cb_;
  Callback        all_finished_cb_;

#if ENABLE_ACTION_LOCK
  mutable std::mutex lock_;
#endif //ENABLE_ACTION_LOCK
};

}

#endif //ACTION_EXECUTOR_H_20221006
